package com.whfc.emp.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.LocaleState;
import com.whfc.common.exception.BizException;
import com.whfc.common.file.FileHandler;
import com.whfc.common.file.FilePathConfig;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.DateUtil;
import com.whfc.common.util.ImageUtil;
import com.whfc.common.util.JSONUtil;
import com.whfc.common.util.PageUtil;
import com.whfc.emp.constant.RealNamePlatformConstant;
import com.whfc.emp.dao.*;
import com.whfc.emp.dto.AppEmpBaiDuFaceAttendDTO;
import com.whfc.emp.dto.AppEmpInputDataDTO;
import com.whfc.emp.dto.AppLocaleStateDTO;
import com.whfc.emp.entity.*;
import com.whfc.emp.enums.AttendState;
import com.whfc.emp.enums.AttendType;
import com.whfc.emp.enums.Direction;
import com.whfc.emp.manager.AppEmpDataManager;
import com.whfc.emp.manager.AppEmpManager;
import com.whfc.emp.manager.FaceBaiDuManager;
import com.whfc.emp.param.AppEmpInputDataAddParam;
import com.whfc.emp.param.FaceGateDataParam;
import com.whfc.emp.realNamePlatform.jingZhou.JINGZHOUApi;
import com.whfc.emp.realNamePlatform.jingZhou.model.WorkerAttendDTO;
import com.whfc.emp.realNamePlatform.jingZhou.model.WorkerEntryExitDTO;
import com.whfc.emp.service.AppEmpInputDataService;
import com.whfc.fuum.entity.WxUser;
import groovyjarjarpicocli.CommandLine;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * @ClasssName AppEmpInputDataServiceImpl
 * @Description 打卡记录
 * @Author hw
 * @Date 2020/12/23 10:12
 * @Version 1.0
 */
@DubboService(interfaceClass = AppEmpInputDataService.class, version = "1.0.0", timeout = 30 * 1000)
public class AppEmpInputDataServiceImpl implements AppEmpInputDataService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AppEmpAttendRecordMapper appEmpAttendRecordMapper;

    @Autowired
    private AppEmpMapper appEmpMapper;

    @Autowired
    private AppEmpDayMapper appEmpDayMapper;

    @Autowired
    private AppEmpDataManager appEmpDataManager;

    @Autowired
    private FaceBaiDuManager faceBaiDuManager;

    @Autowired
    private FilePathConfig filePathConfig;

    @Autowired
    private FileHandler fileHandler;

    @Autowired
    private AppSyncRealNameConfigDao appSyncRealNameConfigDao;

    @Autowired
    private AppEmpGroupMapper appEmpGroupMapper;

    @Override
    public PageData<AppEmpInputDataDTO> list(Integer deptId, Integer pageNum, Integer pageSize, Date startDate, Date endDate, String keyword) {
        logger.info("查询打卡记录列表,deptId:{},pageNum:{},pageSize:{},startDate:{},endDate:{},keyword:{}", deptId, pageNum, pageSize, startDate, endDate, keyword);
        PageHelper.startPage(pageNum, pageSize);
        Date startTime = null;
        Date endTime = null;
        if (startDate != null) {
            startTime = DateUtil.getDateBegin(startDate);
        }
        if (endDate != null) {
            endTime = DateUtil.getDateEnd(endDate);
        }
        PageHelper.startPage(pageNum, pageSize);
        List<AppEmpInputDataDTO> list = appEmpAttendRecordMapper.selectByDeptIdAndDate(deptId, startTime, endTime, keyword, null);
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(AppEmpInputDataAddParam param) {
        logger.info("后台手动添加考勤数据:param:{}", param);
        Integer projectId = param.getDeptId();
        Integer direction = param.getDirection();
        String empName = param.getEmpName();
        String phone = param.getPhone();
        Date time = param.getTime();
        Integer type = param.getType();
        String photo = param.getPhoto();
        Integer empId = param.getEmpId();
        if (param.getEmpId()==null) {
            AppEmp appEmp = null;
            List<AppEmp> appEmpList = appEmpMapper.selectByProjectIdAndEmpName(projectId, empName);
            if (appEmpList.size() == 0) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "姓名输入错误");
            }
            //只有一个匹配 or 手机号为空
            else if (appEmpList.size() == 1 || StringUtils.isEmpty(phone)) {
                appEmp = appEmpList.get(0);
            }
            //多个匹配 and 如果手机号不为空
            else {
                appEmp = appEmpList.stream()
                        .filter(item -> phone.equals(item.getPhone()))
                        .findFirst()
                        .get();
            }
            if (appEmp == null) {
                if (appEmp == null) {
                    throw new BizException(ResultEnum.FAILURE.getCode(), "没有匹配到对应人员信息");
                }
            }

            //初始化每日考勤信息
            empId = appEmp.getId();
        }
        AppEmpDay appEmpDay = this.appEmpDataManager.getEmpDay(empId, time);

        //计算考勤状态
        if (Direction.OUT.getValue().equals(direction)) {
            if (appEmpDay.getStartTime() == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前人员没有进入记录，无法添加出的记录");
            }
            //判断录入时间是否晚于数据库记录时间！如果晚于则用当前时间
            Date endTime = appEmpDay.getEndTime();
            if (endTime == null || time.after(endTime)) {
                appEmpDayMapper.updateEndTime(empId, time);
            }
        } else {
            Date startTime = appEmpDay.getStartTime();
            if (startTime == null || startTime.after(time)) {
                appEmpDayMapper.updateStartTime(empId, time);
                Date endTime = appEmpDay.getEndTime();
                if (endTime != null) {
                    appEmpDayMapper.updateEndTime(empId, endTime);
                }
            }
        }

        appEmpDayMapper.updateAttendStateAndLocaleState(empId, AttendState.ATTEND.getValue(), direction);

        //考勤记录
        AppEmpAttendRecord record = new AppEmpAttendRecord();
        record.setType(type);
        record.setTime(time);
        record.setEmpId(empId);
        record.setDirection(direction);
        record.setDeptId(projectId);
        record.setLat(param.getLat());
        record.setLng(param.getLng());
        record.setLocation(param.getLocation());
        record.setPhoto(photo);
        appEmpAttendRecordMapper.insertSelective(record);

        // 同步考勤记录
        // 查询实名制配置
        AppSyncRealNameConfig appSyncRealNameConfig = appSyncRealNameConfigDao.selectByDeptIdAndPlatform(projectId, RealNamePlatformConstant.JING_ZHOU);
        if (appSyncRealNameConfig != null) {
            Integer empId1 = record.getEmpId();
            CompletableFuture.runAsync(()->{
                AppEmp appEmp = appEmpMapper.selectByPrimaryKey(empId1);
                AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(appEmp.getGroupId());
                JINGZHOUApi.syncAtte(ImageUtil.base64EncodeAndCompress(photo,40),appEmp.getIdCardNo(),appEmpGroup.getGroupCode(),appSyncRealNameConfig,record);
            });
        }
    }

    @Override
    public void del(Integer id) {
        logger.info("删除考勤记录,id:{}", id);
        appEmpAttendRecordMapper.deleteLogicById(id);
    }

    @Override
    public List<AppEmpInputDataDTO> getEmpInputData(Integer deptId, Date startTime, Date endTime,
                                                    AttendType attendType) throws BizException {
        return appEmpAttendRecordMapper.selectByDeptIdAndDate(deptId, startTime, endTime, null, attendType.getValue());
    }


    @Override
    public PageData<AppEmpInputDataDTO> getEmpInputData(List<Integer> deptIdList, Integer pageSum,
                                                        Integer pageSize) throws BizException {
        logger.info("获取人员打卡记录,deptIdList:{}, pageSum:{}, pageSize:{}", deptIdList, pageSum, pageSize);
        PageHelper.startPage(pageSum, pageSize);
        List<AppEmpInputDataDTO> list = appEmpAttendRecordMapper.selectByDeptIdList(deptIdList);
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public void addWithBaiDuFace(WxUser user, AppEmpBaiDuFaceAttendDTO request) throws BizException{
        JSONObject result = faceBaiDuManager.search(request.getImageBase64(), String.valueOf(request.getDeptId()));
        logger.info("人脸比对结果：{}",result);
        int code = result.getInt("error_code");
        if (code == 0) {
            JSONObject jsonObject = result.getJSONObject("result").getJSONArray("user_list").getJSONObject(0);
            String empIds = jsonObject.getString("user_id");
            //====================添加考勤数据=========================
            if (request.getEmpId()!=null&& !empIds.equals(String.valueOf(request.getEmpId()))) {
                logger.info("建筑工人考勤识===>识别员工id={},传参员工id={}",empIds,request.getEmpId());
                throw new BizException(ResultEnum.PARAM_ERROR.getCode(),"识别失败,不是本人");
            }
            Integer empId = Integer.parseInt(empIds);
            // 判断是否在围栏之内
            AppLocaleStateDTO appLocaleStateDTO = appEmpDataManager.calculateLocaleState(request.getDeptId(), empId, request.getLng(), request.getLat(), AttendType.FENCE);
            if (LocaleState.IN.getValue()!=appLocaleStateDTO.getLocaleState().getValue()){
                throw new BizException(ResultEnum.PARAM_ERROR.getCode(),"人员不在围栏区域");
            }
            Date time = new Date();
            AppEmpDay appEmpDay = this.appEmpDataManager.getEmpDay(empId, time);

            //计算考勤状态
            if (Direction.OUT.getValue().equals(request.getDirection())) {
                if (appEmpDay.getStartTime() == null) {
                    throw new BizException(ResultEnum.FAILURE.getCode(), "请先添加进场记录");
                }
                //判断录入时间是否晚于数据库记录时间！如果晚于则用当前时间
                Date endTime = appEmpDay.getEndTime();
                if (endTime == null || time.after(endTime)) {
                    appEmpDayMapper.updateEndTime(empId, time);
                }
            } else {
                Date startTime = appEmpDay.getStartTime();
                if (startTime == null || startTime.after(time)) {
                    appEmpDayMapper.updateStartTime(empId, time);
                    Date endTime = appEmpDay.getEndTime();
                    if (endTime != null) {
                        appEmpDayMapper.updateEndTime(empId, endTime);
                    }
                }
            }

            appEmpDayMapper.updateAttendStateAndLocaleState(empId, AttendState.ATTEND.getValue(), request.getDirection());

            //考勤记录
            AppEmpAttendRecord record = new AppEmpAttendRecord();
            // 管理人员小程序考勤  传了员工id  代表为员工小程序打卡
            record.setType(request.getEmpId()!=null?AttendType.WORKERFACE.getValue():AttendType.ADMINFACE.getValue());
            record.setTime(time);
            record.setEmpId(empId);
            record.setDirection(request.getDirection());
            record.setDeptId(request.getDeptId());
            record.setLat(request.getLat());
            record.setLng(request.getLng());
            record.setPhoto(uploadImg(request.getImageBase64()));
            record.setLocation(request.getLocation());
            appEmpAttendRecordMapper.insertSelective(record);

            // 同步考勤记录
            // 查询实名制配置
            AppSyncRealNameConfig appSyncRealNameConfig = appSyncRealNameConfigDao.selectByDeptIdAndPlatform(request.getDeptId(), RealNamePlatformConstant.JING_ZHOU);
            if (appSyncRealNameConfig != null) {
                CompletableFuture.runAsync(()->{
                    AppEmp appEmp = appEmpMapper.selectByPrimaryKey(empId);
                    AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(appEmp.getGroupId());
                    JINGZHOUApi.syncAtte(ImageUtil.base64Compress(request.getImageBase64(),40),appEmp.getIdCardNo(),appEmpGroup.getGroupCode(),appSyncRealNameConfig,record);
                });
            }
        }else {
            throw new BizException(ResultEnum.FAILURE.getCode(),"识别失败,错误码:"+code);
        }
    }

    @Override
    public List<AppEmpInputDataDTO> list(Integer deptId, Date startDate, Date endDate) {
        Date startTime = null;
        Date endTime = null;
        if (startDate != null) {
            startTime = DateUtil.getDateBegin(startDate);
        }
        if (endDate != null) {
            endTime = DateUtil.getDateEnd(endDate);
        }
        List<AppEmpInputDataDTO> list = appEmpAttendRecordMapper.selectByDeptIdAndDate(deptId, startTime, endTime, null, null);
        return list;
    }

    private String uploadImg(String base64) {
        InputStream inputStream = base64ToInputStream(base64);
        if (inputStream == null) {
            return null;
        }
        String ossKey = filePathConfig.getFilePath("emp/faceGateRecord", String.valueOf(System.currentTimeMillis()));
        return fileHandler.upload(ossKey, inputStream);
    }

    /**
     * base64转化成 inputStream
     *
     * @param base64
     * @return
     */
    public static InputStream base64ToInputStream(String base64) {
        ByteArrayInputStream stream = null;
        try {
            byte[] bytes = Base64.getDecoder().decode(base64);
            stream = new ByteArrayInputStream(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stream;
    }
}
